package com.raymond.service;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.raymond.config.exception.BusinessException;
import com.raymond.entity.commons.BaseEnum;
import com.raymond.entity.commons.BasisOrganizationEntity;
import com.raymond.entity.commons.BasisSupplierEntity;
import com.raymond.entity.commons.BusinessCodeEnum;
import com.raymond.entity.commons.CommonStatusEnum;
import com.raymond.entity.commons.PageResponse;
import com.raymond.entity.settlement.OrderSettlementDetailEntity;
import com.raymond.entity.settlement.OrderSettlementDetailPageQueryReqVo;
import com.raymond.entity.settlement.OrderSettlementEntity;
import com.raymond.entity.settlement.OrderSettlementGroupSummaryEntity;
import com.raymond.entity.settlement.OrderSettlementPageQueryReqVo;
import com.raymond.entity.settlement.OrderSettlementStatusEnum;
import com.raymond.entity.settlement.OrderSettlementTypeEnum;
import com.raymond.mapper.commons.BasisOrganizationMapper;
import com.raymond.mapper.commons.BasisSupplierMapper;
import com.raymond.mapper.settlement.OrderSettlementDetailMapper;
import com.raymond.mapper.settlement.OrderSettlementMapper;
import com.raymond.util.AssertUtil;
import com.raymond.util.BaseEntityUtil;
import com.raymond.util.BusinessIdGenerateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;

/**
 * desc-结算单 服务层实现
 *
 * @author houmenghe
 * @date 2025/04/21 17:34
 **/
@Service
@Slf4j
public class OrderSettlementService {

    private static final List<Integer> FULL_STATUS_LIST = Arrays.asList(10, 20, 30, 40, 50, -100);

    private static final List<String> FULL_DETAIL_NAME_LIST =
            Arrays.asList("螺纹钢", "冲击钻头", "PDU插排",
                    "蒸压加气混凝土砌块", "商品砼", "木模板",
                    "地磅", "人造大理石", "钢筋桁架楼承板", "盘螺");

    private static final List<String> FULL_DETAIL_MODEL_LIST =
            Arrays.asList("规格:Φ20 牌号:HRB400E 卸车:供方卸车", "规格:Φ16 牌号:HRB400E", "规格:Φ14 牌号:HRB400E",
                    "规格:TD1-70", "规格:TD2-90 腹杆:4.5 下弦:8 上弦:8", "规格:TD7-150 腹杆:6 上弦:12",
                    "规格:TD4-80 腹杆:4.5 下弦:10 上弦:10", "规格:657*830*10mm 周转次数:一级板",
                    "规格:798*1530*12mm 周转次数:二级板", "规格:915*1830*15mm 周转次数:三级板");

    private static final List<BigDecimal> FULL_TAX_RATE_LIST = Arrays.asList(BigDecimal.valueOf(0.03), BigDecimal.valueOf(0.05), BigDecimal.valueOf(0.06), BigDecimal.valueOf(0.09), BigDecimal.valueOf(0.13));

    @Autowired
    private OrderSettlementMapper orderSettlementMapper;

    @Autowired
    private OrderSettlementDetailMapper orderSettlementDetailMapper;

    @Autowired
    private BasisOrganizationMapper basisOrganizationMapper;

    @Autowired
    private BasisSupplierMapper basisSupplierMapper;

    public List<OrderSettlementEntity> searchSettlementList(OrderSettlementPageQueryReqVo query) {
        return orderSettlementMapper.searchSettlementPageList(query);
    }

    public int searchSettlementListCount(OrderSettlementPageQueryReqVo query) {
        return orderSettlementMapper.searchSettlementPageListCount(query);
    }

    public Map<String, Long> searchSettlementListSummaryCount(OrderSettlementPageQueryReqVo query) {
        List<OrderSettlementGroupSummaryEntity> result = orderSettlementMapper.searchSettlementPageListSummaryCount(query);
        if (CollectionUtils.isNotEmpty(result)) {
            return result.stream().collect(Collectors.toMap(d -> d.getStatus().getValue().toString(), OrderSettlementGroupSummaryEntity::getCount));
        }
        return null;
    }

    public OrderSettlementEntity getOrderSettlement(Long sysNo) {
        OrderSettlementEntity entity = orderSettlementMapper.searchSettlementBySysNo(sysNo);
        AssertUtil.notNull(entity, "结算单不存在或已删除");
        List<OrderSettlementDetailEntity> detailList = orderSettlementDetailMapper.searchOrderSettlementDetailListBySettlementSysNo(sysNo);
        AssertUtil.notEmpty(detailList, "结算单明细不能为空");
        entity.setDetailList(detailList);
        return entity;
    }

    public PageResponse<OrderSettlementDetailEntity> queryDetailListBySettlementSysNo(OrderSettlementDetailPageQueryReqVo query) {
        AssertUtil.notNull(query, "参数无效");
        AssertUtil.notNull(query.getSettlementSysNo(), "结算单系统编号不能为空");
        OrderSettlementEntity entity = orderSettlementMapper.searchSettlementBySysNo(query.getSettlementSysNo());
        AssertUtil.notNull(entity, "结算单不存在或已删除");

        PageResponse<OrderSettlementDetailEntity> page = PageResponse.create(query);
        List<OrderSettlementDetailEntity> detailList = orderSettlementDetailMapper.searchSettlementDetailPageList(query);
        if (CollectionUtils.isEmpty(detailList)) {
            return page;
        }
        page.setDatas(detailList);
        if (query.isQueryTotal()) {
            page.setTotal(orderSettlementDetailMapper.searchSettlementDetailPageListCount(query));
        }
        return page;
    }

    public void batchInsertMockData(Integer count) {
        if (count < 1) {
            return;
        }

        List<BasisOrganizationEntity> basisOrganizationEntities = basisOrganizationMapper.searchBasisOrganizationFullList();
        List<BasisSupplierEntity> basisSupplierEntities = basisSupplierMapper.searchBasisSupplierFullList();

        Random random = new Random();
        List<OrderSettlementEntity> insertList = new ArrayList<>();
        List<OrderSettlementDetailEntity> detailList = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            BasisOrganizationEntity organizationEntity = basisOrganizationEntities.get(random.nextInt(basisOrganizationEntities.size() - 1));
            BasisSupplierEntity supplierEntity = basisSupplierEntities.get(random.nextInt(basisSupplierEntities.size() - 1));

            OrderSettlementEntity insert = new OrderSettlementEntity();
            insert.setSysNo(BusinessIdGenerateUtil.getSnowId());
            insert.setOrganizationSysNo(organizationEntity.getSysNo());
            insert.setSupplierSysNo(supplierEntity.getSysNo());
            insert.setContractSysNo(null);
            insert.setSettlementDate(new Date());
            insert.setComment(null);
            insert.setAuditType(null);
            insert.setAuditStatus(null);
            insert.setAuditFlowInstanceId(null);
            insert.setAuditFlowInstanceType(null);
            insert.setAuditPassDate(null);
            insert.setSettlementType(BaseEnum.getEnumByValue(OrderSettlementTypeEnum.class, (i%9+1)));
            insert.setCode(BusinessIdGenerateUtil.generate(convertSettlementTypeToBusinessCodePrefix(insert.getSettlementType())));
            insert.setName(generateName(i, insert.getSettlementDate(), organizationEntity.getOrganizationName()));
            insert.setStatus(BaseEnum.getEnumByValue(OrderSettlementStatusEnum.class, FULL_STATUS_LIST.get(i%6)));
            insert.setParentSettlementSysNo(null);
            insert.setInvalidReason(null);
            insert.setNotice(null);
            insert.setBillDueDate(DateUtil.beginOfDay(DateUtil.offsetDay(new Date(), 30 + random.nextInt(20))));
            BaseEntityUtil.buildMockUserInfo(insert);
            insert.setCommonStatus(CommonStatusEnum.OK);

            int detailCount = random.nextInt(30) + 1;
            BigDecimal amount = BigDecimal.ZERO;
            for (int j = 0; j < detailCount; j++) {
                OrderSettlementDetailEntity detail = new OrderSettlementDetailEntity();
                detail.setSysNo(BusinessIdGenerateUtil.getSnowId());
                detail.setOrderSettlementSysNo(insert.getSysNo());
                detail.setName(FULL_DETAIL_NAME_LIST.get(random.nextInt(FULL_DETAIL_NAME_LIST.size() - 1)));
                detail.setModel(FULL_DETAIL_MODEL_LIST.get(random.nextInt(FULL_DETAIL_MODEL_LIST.size() - 1)));
                detail.setPrice(BigDecimal.valueOf(Math.random()).multiply(BigDecimal.valueOf(Math.pow(10, (i%3+1))).setScale(8, RoundingMode.HALF_UP)));
                detail.setOriginalPrice(detail.getPrice());
                detail.setTaxRate(FULL_TAX_RATE_LIST.get(i%5));
                detail.setIncludeTaxPrice(detail.getPrice().multiply(detail.getTaxRate().add(BigDecimal.ONE)).setScale(8, RoundingMode.HALF_UP));
                detail.setOriginalIncludeTaxPrice(detail.getIncludeTaxPrice());
                detail.setQuantity(BigDecimal.valueOf(Math.random()).multiply(BigDecimal.valueOf(Math.pow(10, (i%2+1))).setScale(8, RoundingMode.HALF_UP)));
                detail.setAmount(detail.getIncludeTaxPrice().multiply(detail.getQuantity()).setScale(2, RoundingMode.HALF_UP));
                detail.setAmountExcludeTax(detail.getPrice().multiply(detail.getQuantity()).setScale(2, RoundingMode.HALF_UP));
                detail.setTax(detail.getAmount().subtract(detail.getAmountExcludeTax()).setScale(2, RoundingMode.HALF_UP));
                detail.setBrandSysNo(null);
                detail.setBrandName(null);
                detail.setUnitSysNo(null);
                detail.setUnitName(null);
                detail.setComment(null);
                BaseEntityUtil.fillUserInfo(insert, detail);
                detail.setCommonStatus(CommonStatusEnum.OK);
                amount = amount.add(detail.getAmount());
                detailList.add(detail);
            }

            insert.setAmount(amount);
            insert.setOtherAmount(BigDecimal.valueOf(Math.random()).multiply(BigDecimal.valueOf(Math.pow(10, (i%3+1)))).setScale(2, RoundingMode.HALF_UP));
            insert.setTotalAmount(insert.getAmount().add(insert.getOtherAmount()).setScale(2, RoundingMode.HALF_UP));
            insertList.add(insert);
        }
        orderSettlementMapper.batchInsert(insertList);
        orderSettlementDetailMapper.batchInsertOrderSettlementDetail(detailList);
    }

    private String convertSettlementTypeToBusinessCodePrefix(OrderSettlementTypeEnum settlementType) {
        AssertUtil.notNull(settlementType, "结算类型不能为空");
        switch (settlementType) {
            case PURCHASE:
                return BusinessCodeEnum.PURCHASE.getValue();
            case MALL:
                return BusinessCodeEnum.MALL.getValue();
            case CONCRETE:
                return BusinessCodeEnum.CONCRETE.getValue();
            case TRADITION_LEASE:
                return BusinessCodeEnum.TRADITION_LEASE.getValue();
            case SPECIAL_ITEM:
                return BusinessCodeEnum.SPECIAL_ITEM.getValue();
            case VEHICLE:
                return BusinessCodeEnum.VEHICLE.getValue();
            case EXPENSE:
                return BusinessCodeEnum.EXPENSE.getValue();
            case MALL_LEASE:
                return BusinessCodeEnum.MALL_LEASE.getValue();
            case FREIGHT:
                return BusinessCodeEnum.FREIGHT.getValue();
            default:
                throw new BusinessException("未知的结算类型");
        }
    }

    private String generateName(int index, Date settlementDate, String name) {
        // index如果大于999，截取后三位
        index = index % 1000;
        String seqStr = String.format("%03d", index+1);
        String todayStr = DateUtil.format(settlementDate, DatePattern.PURE_DATE_PATTERN);
        String seq = todayStr + "-" + seqStr;
        return String.format("%s结算单-%s", name, seq);
    }
}
